<?php

namespace app\admin\service\addons;

use app\admin\service\file\FileService;
use app\common\model\addons\Addons as AddonsModel;
use app\common\model\file\File as FileModel;
use tmcore\base\BaseService;
use tmcore\exceptions\AddonsException;
use tmcore\services\addons\AddonApiService;
use tmcore\services\addons\CoreService;
use tmcore\services\addons\ModelService;
use tmcore\services\addons\TerminalService;
use tmcore\services\addons\UtilService;
use tmcore\services\CaptchaService;
use tmcore\services\ConfigService;
use tmcore\utils\File;

class ManageService extends BaseService
{
    /**
     * 用户信息
     * @return array
     */
    public static function userInfo()
    {
        $auth_config = AddonApiService::getAuthConfig('get');

        return [
            'account' => $auth_config['account'],
            'project_name' => $auth_config['project_name'],
            'is_login' => $auth_config['is_login'],
        ];
    }

    /**
     * 用户登录
     * @param $params
     * @return mixed
     * @throws AddonsException|\tmcore\exceptions\ValidateException
     */
    public static function login($params)
    {
        // 验证码检验
        if(!empty($params['captchaUniqid']) && !empty($params['code']))CaptchaService::codeVerify($params);
        return AddonApiService::user_token(['account' => $params['account'], 'password' => $params['password']], true);
    }

    /**
     * 用户登录
     * @return bool
     * @throws AddonsException
     */
    public static function logout()
    {
        return AddonApiService::user_logout();
    }

    /**
     * 刷新缓存
     * @return bool
     */
    public static function refresh()
    {
        (new ConfigService)->setConfig('create', 'sys', 'auth');
        return true;
    }

    /**
     * 获取应用列表
     * @param $params
     * @return array
     * @throws AddonsException
     */
    public static function getList($params)
    {
        $list = AddonApiService::get_addons_list($params);
        if(isset($list['list'])) {
            foreach ($list['list'] as &$addon) {
                $local_row = AddonsModel::where(['identify' => $addon['identify']])->findOrEmpty();
                if(!$local_row->isEmpty()) {
                    $addon['local'] = $local_row->toArray();
                } else {
                    $addon['local'] = [];
                }
            }
        }

        return $list;
    }


    /**
     * 获取本地应用
     * @return array
     */
    public static function getLocalList(): array
    {
        $searchParam = [
            '=' => ['status'],
            '%like%' => ['name']
        ];
        $where = self::getSearchData($searchParam, []);

        // 返回分页数据
        $list = AddonsModel::page($where, self::getPageData(), '*', ['id' => 'desc'], ['status_desc']);

        foreach ($list['list'] as &$item) {
            $item['thumb'] = get_file_url($item['thumb']);
        }
        return $list;
    }

    /**
     * 获取应用详情
     * @param $params
     * @return array
     */
    public static function getDetail($params): array
    {
        $addon_row = AddonApiService::get_addons_info($params['identify']);

        if(!empty($addon_row['identify'])) {
            $local_row = AddonsModel::where(['identify' => $params['identify']])->findOrEmpty();
            if($local_row->isEmpty()) {
                $addon_row['local'] = [];
                $addon_row['update_version'] = '';
            } else {
                $addon_row['local'] = $local_row->toArray();
                $addon_row['update_version'] = '';

                if(isset($addon_row['update_list']) && $addon_row['update_list']) {
                    foreach ($addon_row['update_list'] as $update_item) {
                        // 找到临近待更新版本号
                        if(version_compare($update_item['version'], $local_row['version']) > 0) {
                            $addon_row['update_version'] = $update_item['version'];
                        }
                    }
                }

            }
        }

        return $addon_row;
    }

    /**
     * 获取本地应用详情
     * @param $params
     * @return array
     */
    public static function getLocalDetail($params): array
    {
         $row = AddonsModel::where(['id' => $params['id'], 'is_local' => 1])->findOrEmpty();
         if(!$row->isEmpty()) {
             $row = $row->toArray();
             $row['file_url'] =  'data/download/addons/' . $row['identify'] . '/'  . $row['version'] . '.zip';
             return $row;
         } else {
             return [];
         }
    }

    /**
     * 插件下载
     * @param $params
     * @return bool
     */
    public static function downloadAddon($params)
    {

        $savePath = com_get_path('data') . 'download/addons/' . $params['identify'];

        $zipPath = $savePath. '/'. $params['version'] .'.zip';

        if(!file_exists($zipPath)) {
            // 接口下载版本包
            AddonApiService::addons_version_download($params['identify'], $params['version'], $savePath);
        }

        $addonPath = com_get_path('data') . 'addons/' . $params['identify'];
        if(!is_dir($addonPath)) mkdir($addonPath,0755,true);
        // 清空目录
        File::del_dir($addonPath);

        // 解压版本包
        $res = File::unzip($zipPath, $addonPath);
        if(!$res) return self::setError('解压下载的压缩包失败');

        return true;
    }

    /**
     * 命令信息
     * @param $params
     * @return false|string
     */
    public static function getCommandExecInfo()
    {
        $res = (new TerminalService())->getExecResult();
        if($res) {
            return $res['result'];
        } else {
            return self::setError('执行命令失败');
        }
    }

    /**
     * 插件导入
     * @param $params
     * @return true
     */
    public static function addonImport($params)
    {
        try {
            if(!in_array($params['operate_type'], ['install','update'])) throw new \Exception('类型参数有误');

            $addon_row = (new ModelService())->getInfoByKey($params['identify']);

            if($params['operate_type'] == 'install') {
                if($addon_row) throw new \Exception('插件标识重复有误');
            } else {
                if(version_compare($addon_row['version'], $params['version']) >= 0) throw new \Exception('上传版本号必须大于当前版本');
            }

            $addonPath = com_get_path('data') . 'addons/'. $params['identify'];
            $downloadPath = com_get_path('data') . 'download/addons/' . $params['identify'];
            $zipPath = $downloadPath . '/'  . $params['version'] . '.zip';

            // 检测是否上传新压缩包
            if(strpos($params['file_url'], 'uploads/files') !== false) {
                $file_row = FileModel::where(['uri' => $params['file_url']])->field('id, size, ext')->findOrEmpty()->toArray();
                if($file_row) {
                    if($file_row['ext'] != 'zip') throw new \Exception('上传压缩包格式有误');

                    // 删除并转移压缩包
                    $file_url = app()->getRootPath() . 'public'. '/' . $params['file_url'];
                    if(file_exists($file_url)) {
                        if(!is_dir($addonPath)) mkdir($addonPath , 0755, true);
                        if(!is_dir($downloadPath)) mkdir($downloadPath, 0755, true);
                        if(file_exists($zipPath)) @unlink($zipPath);
                        $res = copy($file_url, $zipPath);
                        if(!$res) throw new \Exception('转移压缩包失败');
                        // 删除上传压缩包
                        (new FileService)->delete(['ids' => $file_row['id']]);
                    }
                }
            }

            // 清空目录
            File::del_dir($addonPath);

            // 解压版本包
            $res = File::unzip($zipPath, $addonPath);
            if(!$res) return self::setError('解压上传的压缩包失败');

            if($params['operate_type'] == 'install') {
                (new CoreService($params['identify']))->install([
                    'name' => $params['name'],
                    'identify' => $params['identify'],
                    'thumb' => $params['thumb']?? '',
                    'version' => $params['version'],
                ], true);
            } else {
                (new CoreService($params['identify']))->update([
                    'name' => $params['name'],
                    'identify' => $params['identify'],
                    'thumb' => $params['thumb']?? '',
                    'version' => $params['version'],
                ], true);
            }

            return true;
        } catch (\Exception $e) {

            if((!empty($params['identify'])) || (!empty($params['version']))) {
                $addon_row = (new ModelService())->getInfoByKey($params['identify']);
                $is_check = true;
                if($params['operate_type'] == 'install') {
                    if($addon_row) $is_check = false;
                } else {
                    if(version_compare($addon_row['version'], $params['version']) >= 0) $is_check = false;;
                }
                // 清空上传的异常压缩包
                if($is_check) {
                    $zipPath = com_get_path('data') . 'download/addons/' . $params['identify'] . '/'  . $params['version'] . '.zip';
                    if(file_exists($zipPath)) @unlink($zipPath);
                }
            }

            return self::setError($e->getMessage());
        }

    }

    /**
     * 获取依赖
     * @param $params
     * @return array
     */
    public static function getDepends($params)
    {
        $savePath = com_get_path('data') . 'addons/' . $params['identify'];

        $depends_list = [];

        if(file_exists($savePath . '/package/composer.json')) {
            $result = UtilService::getJsonFileContent($savePath . '/package/composer.json');
            if(!empty($result['require'])) {
                $depends_list = self::addDependDataList($result['require'], 'composer', 'server', 'require', $depends_list);
            }
            if(!empty($result['require-dev'])) {
                $depends_list = self::addDependDataList($result['require-dev'], 'composer', 'server','require-dev', $depends_list);
            }
        }

        if(file_exists($savePath . '/package/admin_package.json')) {
            $result = UtilService::getJsonFileContent($savePath . '/package/admin_package.json');
            if(!empty($result['dependencies'])) {
                $depends_list = self::addDependDataList($result['dependencies'], 'npm', 'admin', 'dependencies', $depends_list);
            }
            if(!empty($result['devDependencies'])) {
                $depends_list = self::addDependDataList($result['devDependencies'], 'npm', 'admin', 'devDependencies', $depends_list);
            }
        }

        if(file_exists($savePath . '/package/uniapp_package.json')) {
            $result = UtilService::getJsonFileContent($savePath . '/package/uniapp_package.json');
            if(!empty($result['dependencies'])) {
                $depends_list = self::addDependDataList($result['dependencies'], 'npm', 'uniapp', 'dependencies', $depends_list);
            }
            if(!empty($result['devDependencies'])) {
                $depends_list = self::addDependDataList($result['devDependencies'], 'npm', 'uniapp', 'devDependencies', $depends_list);
            }
        }

        if(file_exists($savePath . '/package/pc_package.json')) {
            $result = UtilService::getJsonFileContent($savePath . '/package/pc_package.json');
            if(!empty($result['dependencies'])) {
                $depends_list = self::addDependDataList($result['dependencies'], 'npm', 'pc', 'dependencies', $depends_list);
            }
            if(!empty($result['devDependencies'])) {
                $depends_list = self::addDependDataList($result['devDependencies'], 'npm', 'pc', 'devDependencies', $depends_list);
            }
        }

        return $depends_list;
    }

    /**
     * 获取执行命令
     * @param $params
     * @return array|bool
     */
    public static function getCommands($params)
    {
        if(!in_array($params['operate_type'], ['install','uninstall','update'])) return self::setError('操作类型有误');
        return UtilService::getExecCommands($params['identify']);
    }

    /**
     * 添加依赖数据
     * @param $list
     * @param $type
     * @param $module
     * @param $setting
     * @param array $data
     * @return array|mixed
     */
    private static function addDependDataList($list, $type, $module, $setting, $data = [])
    {
        foreach ($list as $key => $value) {
            $data[] = [
                'depend' => $key,
                'version' => $value,
                'type' => $type,
                'module' => $module,
                'setting' => $setting,
                'is_select' => 0
            ];
        }
        return $data;
    }

}